from django.db import models
from django.utils import timezone
from django.contrib.auth import get_user_model
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes.fields import GenericForeignKey
import json

User = get_user_model()


class ReportTemplate(models.Model):
    """
    报表模板模型
    """
    REPORT_TYPES = [
        ('portfolio_performance', '投资组合绩效报告'),
        ('risk_analysis', '风险分析报告'),
        ('asset_allocation', '资产配置报告'),
        ('transaction_summary', '交易汇总报告'),
        ('market_analysis', '市场分析报告'),
        ('compliance', '合规报告'),
        ('custom', '自定义报告'),
    ]
    
    FORMAT_TYPES = [
        ('pdf', 'PDF'),
        ('excel', 'Excel'),
        ('csv', 'CSV'),
        ('json', 'JSON'),
        ('html', 'HTML'),
    ]
    
    FREQUENCY_CHOICES = [
        ('once', '一次性'),
        ('daily', '每日'),
        ('weekly', '每周'),
        ('monthly', '每月'),
        ('quarterly', '每季度'),
        ('yearly', '每年'),
    ]
    
    name = models.CharField(max_length=100, verbose_name='模板名称')
    description = models.TextField(blank=True, verbose_name='模板描述')
    report_type = models.CharField(max_length=30, choices=REPORT_TYPES, verbose_name='报告类型')
    format_type = models.CharField(max_length=10, choices=FORMAT_TYPES, default='pdf', verbose_name='输出格式')
    
    # 模板配置
    template_config = models.JSONField(default=dict, verbose_name='模板配置')
    data_sources = models.JSONField(default=list, verbose_name='数据源配置')
    filters = models.JSONField(default=dict, verbose_name='过滤条件')
    charts = models.JSONField(default=list, verbose_name='图表配置')
    
    # 调度配置
    is_scheduled = models.BooleanField(default=False, verbose_name='是否定时生成')
    frequency = models.CharField(max_length=20, choices=FREQUENCY_CHOICES, default='once', verbose_name='生成频率')
    schedule_time = models.TimeField(null=True, blank=True, verbose_name='调度时间')
    
    # 权限配置
    is_public = models.BooleanField(default=False, verbose_name='是否公开')
    allowed_users = models.ManyToManyField(User, blank=True, verbose_name='允许访问的用户')
    
    created_by = models.ForeignKey(User, on_delete=models.CASCADE, related_name='created_templates', verbose_name='创建者')
    is_active = models.BooleanField(default=True, verbose_name='是否启用')
    created_at = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
    updated_at = models.DateTimeField(auto_now=True, verbose_name='更新时间')
    
    class Meta:
        db_table = 'report_template'
        verbose_name = '报表模板'
        verbose_name_plural = '报表模板'
        ordering = ['-created_at']
    
    def __str__(self):
        return self.name
    
    def get_data_source_config(self, source_name):
        """
        获取指定数据源配置
        """
        for source in self.data_sources:
            if source.get('name') == source_name:
                return source
        return None
    
    def get_chart_config(self, chart_id):
        """
        获取指定图表配置
        """
        for chart in self.charts:
            if chart.get('id') == chart_id:
                return chart
        return None


class Report(models.Model):
    """
    报表记录模型
    """
    STATUS_CHOICES = [
        ('pending', '待生成'),
        ('generating', '生成中'),
        ('completed', '已完成'),
        ('failed', '生成失败'),
        ('cancelled', '已取消'),
    ]
    
    template = models.ForeignKey(ReportTemplate, on_delete=models.CASCADE, verbose_name='报表模板')
    name = models.CharField(max_length=200, verbose_name='报表名称')
    description = models.TextField(blank=True, verbose_name='报表描述')
    
    # 生成参数
    parameters = models.JSONField(default=dict, verbose_name='生成参数')
    filters = models.JSONField(default=dict, verbose_name='过滤条件')
    
    # 时间范围
    start_date = models.DateField(verbose_name='开始日期')
    end_date = models.DateField(verbose_name='结束日期')
    
    # 状态和结果
    status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='pending', verbose_name='状态')
    file_path = models.CharField(max_length=500, blank=True, verbose_name='文件路径')
    file_size = models.BigIntegerField(null=True, blank=True, verbose_name='文件大小(字节)')
    
    # 生成信息
    generated_by = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name='生成者')
    generated_at = models.DateTimeField(null=True, blank=True, verbose_name='生成时间')
    completed_at = models.DateTimeField(null=True, blank=True, verbose_name='完成时间')
    
    # 错误信息
    error_message = models.TextField(blank=True, verbose_name='错误信息')
    
    # 统计信息
    data_rows = models.IntegerField(null=True, blank=True, verbose_name='数据行数')
    generation_duration = models.FloatField(null=True, blank=True, verbose_name='生成耗时(秒)')
    
    # 访问控制
    is_public = models.BooleanField(default=False, verbose_name='是否公开')
    shared_users = models.ManyToManyField(User, blank=True, related_name='shared_reports', verbose_name='共享用户')
    
    created_at = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
    updated_at = models.DateTimeField(auto_now=True, verbose_name='更新时间')
    
    class Meta:
        db_table = 'report'
        verbose_name = '报表记录'
        verbose_name_plural = '报表记录'
        ordering = ['-created_at']
        indexes = [
            models.Index(fields=['template', 'status']),
            models.Index(fields=['generated_by', 'created_at']),
            models.Index(fields=['status', 'generated_at']),
        ]
    
    def __str__(self):
        return f"{self.name} - {self.get_status_display()}"
    
    def mark_as_generating(self):
        """
        标记为生成中
        """
        self.status = 'generating'
        self.generated_at = timezone.now()
        self.save(update_fields=['status', 'generated_at', 'updated_at'])
    
    def mark_as_completed(self, file_path, file_size=None, data_rows=None):
        """
        标记为已完成
        """
        self.status = 'completed'
        self.file_path = file_path
        self.file_size = file_size
        self.data_rows = data_rows
        self.completed_at = timezone.now()
        
        if self.generated_at:
            duration = (self.completed_at - self.generated_at).total_seconds()
            self.generation_duration = duration
        
        self.save(update_fields=[
            'status', 'file_path', 'file_size', 'data_rows', 
            'completed_at', 'generation_duration', 'updated_at'
        ])
    
    def mark_as_failed(self, error_message):
        """
        标记为失败
        """
        self.status = 'failed'
        self.error_message = error_message
        self.completed_at = timezone.now()
        
        if self.generated_at:
            duration = (self.completed_at - self.generated_at).total_seconds()
            self.generation_duration = duration
        
        self.save(update_fields=[
            'status', 'error_message', 'completed_at', 
            'generation_duration', 'updated_at'
        ])
    
    def get_file_url(self):
        """
        获取文件下载URL
        """
        if self.file_path and self.status == 'completed':
            from django.urls import reverse
            return reverse('reporting:download_report', kwargs={'report_id': self.id})
        return None


class ReportSchedule(models.Model):
    """
    报表调度模型
    """
    STATUS_CHOICES = [
        ('active', '活跃'),
        ('paused', '暂停'),
        ('disabled', '禁用'),
    ]
    
    template = models.ForeignKey(ReportTemplate, on_delete=models.CASCADE, verbose_name='报表模板')
    name = models.CharField(max_length=100, verbose_name='调度名称')
    description = models.TextField(blank=True, verbose_name='调度描述')
    
    # 调度配置
    frequency = models.CharField(max_length=20, choices=ReportTemplate.FREQUENCY_CHOICES, verbose_name='执行频率')
    schedule_time = models.TimeField(verbose_name='执行时间')
    timezone = models.CharField(max_length=50, default='Asia/Shanghai', verbose_name='时区')
    
    # 参数配置
    default_parameters = models.JSONField(default=dict, verbose_name='默认参数')
    
    # 状态
    status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='active', verbose_name='状态')
    
    # 执行记录
    last_run_time = models.DateTimeField(null=True, blank=True, verbose_name='上次执行时间')
    next_run_time = models.DateTimeField(null=True, blank=True, verbose_name='下次执行时间')
    run_count = models.IntegerField(default=0, verbose_name='执行次数')
    success_count = models.IntegerField(default=0, verbose_name='成功次数')
    failure_count = models.IntegerField(default=0, verbose_name='失败次数')
    
    created_by = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name='创建者')
    created_at = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
    updated_at = models.DateTimeField(auto_now=True, verbose_name='更新时间')
    
    class Meta:
        db_table = 'report_schedule'
        verbose_name = '报表调度'
        verbose_name_plural = '报表调度'
        ordering = ['-created_at']
    
    def __str__(self):
        return f"{self.name} - {self.get_frequency_display()}"
    
    def calculate_next_run_time(self):
        """
        计算下次执行时间
        """
        from datetime import datetime, timedelta
        import pytz
        
        tz = pytz.timezone(self.timezone)
        now = timezone.now().astimezone(tz)
        
        if self.frequency == 'daily':
            next_run = now.replace(hour=self.schedule_time.hour, minute=self.schedule_time.minute, second=0, microsecond=0)
            if next_run <= now:
                next_run += timedelta(days=1)
        elif self.frequency == 'weekly':
            # 假设每周一执行
            days_ahead = 0 - now.weekday()
            if days_ahead <= 0:
                days_ahead += 7
            next_run = now + timedelta(days=days_ahead)
            next_run = next_run.replace(hour=self.schedule_time.hour, minute=self.schedule_time.minute, second=0, microsecond=0)
        elif self.frequency == 'monthly':
            # 每月1号执行
            if now.day == 1 and now.time() < self.schedule_time:
                next_run = now.replace(hour=self.schedule_time.hour, minute=self.schedule_time.minute, second=0, microsecond=0)
            else:
                if now.month == 12:
                    next_run = now.replace(year=now.year + 1, month=1, day=1, hour=self.schedule_time.hour, minute=self.schedule_time.minute, second=0, microsecond=0)
                else:
                    next_run = now.replace(month=now.month + 1, day=1, hour=self.schedule_time.hour, minute=self.schedule_time.minute, second=0, microsecond=0)
        else:
            next_run = now + timedelta(days=1)
        
        self.next_run_time = next_run.astimezone(timezone.utc)
        self.save(update_fields=['next_run_time'])
        
        return self.next_run_time
    
    def record_execution(self, success=True):
        """
        记录执行结果
        """
        self.last_run_time = timezone.now()
        self.run_count += 1
        
        if success:
            self.success_count += 1
        else:
            self.failure_count += 1
        
        self.save(update_fields=['last_run_time', 'run_count', 'success_count', 'failure_count'])
        self.calculate_next_run_time()


class ReportData(models.Model):
    """
    报表数据缓存模型
    """
    report = models.ForeignKey(Report, on_delete=models.CASCADE, verbose_name='报表')
    data_key = models.CharField(max_length=100, verbose_name='数据键')
    data_value = models.JSONField(verbose_name='数据值')
    
    # 缓存信息
    cache_key = models.CharField(max_length=200, verbose_name='缓存键')
    expires_at = models.DateTimeField(verbose_name='过期时间')
    
    created_at = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
    
    class Meta:
        db_table = 'report_data'
        verbose_name = '报表数据'
        verbose_name_plural = '报表数据'
        unique_together = ['report', 'data_key']
        indexes = [
            models.Index(fields=['cache_key', 'expires_at']),
            models.Index(fields=['report', 'data_key']),
        ]
    
    def __str__(self):
        return f"{self.report.name} - {self.data_key}"
    
    def is_expired(self):
        """
        检查是否过期
        """
        return timezone.now() > self.expires_at


class ReportSubscription(models.Model):
    """
    报表订阅模型
    """
    STATUS_CHOICES = [
        ('active', '活跃'),
        ('paused', '暂停'),
        ('cancelled', '已取消'),
    ]
    
    DELIVERY_METHODS = [
        ('email', '邮件'),
        ('download', '下载链接'),
        ('api', 'API推送'),
    ]
    
    user = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name='订阅用户')
    template = models.ForeignKey(ReportTemplate, on_delete=models.CASCADE, verbose_name='报表模板')
    
    # 订阅配置
    name = models.CharField(max_length=100, verbose_name='订阅名称')
    delivery_method = models.CharField(max_length=20, choices=DELIVERY_METHODS, default='email', verbose_name='交付方式')
    delivery_config = models.JSONField(default=dict, verbose_name='交付配置')
    
    # 参数配置
    parameters = models.JSONField(default=dict, verbose_name='报表参数')
    
    # 状态
    status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='active', verbose_name='状态')
    
    # 统计信息
    delivery_count = models.IntegerField(default=0, verbose_name='交付次数')
    last_delivery_time = models.DateTimeField(null=True, blank=True, verbose_name='上次交付时间')
    
    created_at = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
    updated_at = models.DateTimeField(auto_now=True, verbose_name='更新时间')
    
    class Meta:
        db_table = 'report_subscription'
        verbose_name = '报表订阅'
        verbose_name_plural = '报表订阅'
        unique_together = ['user', 'template', 'name']
    
    def __str__(self):
        return f"{self.user.username} - {self.template.name}"
    
    def record_delivery(self):
        """
        记录交付
        """
        self.delivery_count += 1
        self.last_delivery_time = timezone.now()
        self.save(update_fields=['delivery_count', 'last_delivery_time', 'updated_at'])